package com.ruoyi.teaching.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.li.work.mapper.SysDeptMapper;
import com.ruoyi.li.work.mapper.SysUserMapper;
import com.ruoyi.li.work.mapper.SysUserRoleMapper;
import com.ruoyi.teaching.domain.Option;
import com.ruoyi.teaching.domain.PlatformQQuestion;
import com.ruoyi.teaching.domain.TimePeriod;
import com.ruoyi.teaching.domain.UniversalCreateUpdate;
import com.ruoyi.teaching.domain.vo.PlatformQQuestionVO;
import com.ruoyi.teaching.domain.vo.PlatformUUserDeptVO;
import com.ruoyi.teaching.domain.vo.ScoreInfoInVO;
import com.ruoyi.teaching.domain.vo.ScoreInfoOutVO;
import com.ruoyi.teaching.mapper.PlatformQQuestionMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;

/**
 * 通用工具类
 */
public class UniversalUtil {

    private static final Pattern SPECIAL_CHAR_PATTERN = Pattern.compile("[^a-zA-Z0-9\u4E00-\u9FA5]");   //匹配所有非字母、非数字和非中文字符

    public static UniversalCreateUpdate getCreateUpdate(SysUserMapper sysUserMapper) {
        UniversalCreateUpdate universalCreateUpdate = new UniversalCreateUpdate();
        Long il = null;
        try {
            il = SecurityUtils.getUserId();
        } catch (ServiceException e) {
            throw new RuntimeException("请先登录");
        }
        int i = SecurityUtils.getUserId().intValue();
        String nickName = sysUserMapper.selectUserById(il).getNickName();
        universalCreateUpdate.setId(i);
        universalCreateUpdate.setName(nickName);
        return universalCreateUpdate;
    }

    //拼接子部门和父部门的名字
    public static List<PlatformUUserDeptVO> getDeptWithParentNames(Integer[] deptIds, SysDeptMapper sysDeptMapper) {
        // 存储部门和父部门的映射
        Map<Long, SysDept> deptMap = new HashMap<>();
        Set<Long> parentIds = new HashSet<>();

        // 获取子部门信息并收集父部门ID
        for (Integer deptId : deptIds) {
            long deptIdLong = deptId.longValue();
            SysDept sysDept = sysDeptMapper.selectDeptById(deptIdLong);
            if (sysDept != null) {
                deptMap.put(sysDept.getDeptId(), sysDept);
                parentIds.add(sysDept.getParentId());
            }
        }

        // 获取所有父部门信息
        for (Long parentId : parentIds) {
            if (!deptMap.containsKey(parentId)) {
                SysDept parentDept = sysDeptMapper.selectDeptById(parentId);
                if (parentDept != null) {
                    deptMap.put(parentDept.getDeptId(), parentDept);
                }
            }
        }

        // 构建返回结果
        List<PlatformUUserDeptVO> platformUUserDeptVOS = new ArrayList<>();
        for (SysDept childDept : deptMap.values()) {
            SysDept parentDept = deptMap.get(childDept.getParentId());
            if (parentDept != null) {
                PlatformUUserDeptVO platformUUserDeptVO = new PlatformUUserDeptVO();
                platformUUserDeptVO.setDeptId(childDept.getDeptId().intValue());
                platformUUserDeptVO.setDeptName(parentDept.getDeptName() + childDept.getDeptName());
                platformUUserDeptVOS.add(platformUUserDeptVO);
            }
        }

        return platformUUserDeptVOS;
    }



    // 将 PlatformQQuestionVO 转换为 PlatformQQuestion，同时处理数组和字符串的相互转换
    public static PlatformQQuestion arrayToString(PlatformQQuestionVO platformQQuestionVO) {
        PlatformQQuestion platformQQuestion = new PlatformQQuestion();
        BeanUtils.copyProperties(platformQQuestionVO, platformQQuestion);

        // 将 options 列表转换为 JSON 字符串
        String options = JSON.toJSONString(platformQQuestionVO.getOptions());
        platformQQuestion.setOptions(options);

        // 将 questionAnswerMore 数组转换为逗号分隔的字符串
        if (platformQQuestionVO.getQuestionAnswerMore() != null && platformQQuestionVO.getQuestionAnswerMore().length > 0) {
            String questionAnswerMore = String.join(",", platformQQuestionVO.getQuestionAnswerMore());
            platformQQuestion.setQuestionAnswerMore(questionAnswerMore);
        }

        return platformQQuestion;
    }

    // 将 PlatformQQuestion 转换为 PlatformQQuestionVO，同时处理字符串和数组的相互转换
    public static PlatformQQuestionVO stringToArray(PlatformQQuestion record) {
        if(null == record){
            throw new RuntimeException("暂无数据");
        }
        PlatformQQuestionVO platformQQuestionVO = new PlatformQQuestionVO();
        BeanUtils.copyProperties(record, platformQQuestionVO);

        // 将 JSON 字符串转换为 options 列表
        List<Option> options = JSONArray.parseArray(record.getOptions(), Option.class);
        platformQQuestionVO.setOptions(options);

        // 将逗号分隔的字符串转换为 questionAnswerMore 数组
        if (record.getQuestionAnswerMore() != null && !record.getQuestionAnswerMore().isEmpty()) {
            String[] questionAnswerMore = record.getQuestionAnswerMore().split(",");
            platformQQuestionVO.setQuestionAnswerMore(questionAnswerMore);
        }

        return platformQQuestionVO;
    }

    // 解析并处理分数信息
    public static List<ScoreInfoOutVO> parseAndProcessScoreInformation(List<ScoreInfoInVO> scoreInfoInVOS, PlatformQQuestionMapper platformQQuestionMapper){
        List<ScoreInfoOutVO> scoreInfoOutVOS = new ArrayList<>();
        for (ScoreInfoInVO scoreInfoInVO : scoreInfoInVOS) {
            PlatformQQuestion platformQQuestion = platformQQuestionMapper.selectById(scoreInfoInVO.getId());
            PlatformQQuestionVO platformQQuestionVO = UniversalUtil.stringToArray(platformQQuestion);
            ScoreInfoOutVO scoreInfoOutVO = new ScoreInfoOutVO();
            BeanUtils.copyProperties(platformQQuestionVO, scoreInfoOutVO);
            scoreInfoOutVO.setQuestionValue(scoreInfoInVO.getQuestionValue());
            // 将逗号分隔的字符串转换为 myAnswer 数组
            if(platformQQuestion.getQuestionType() == 1){
                if (scoreInfoInVO.getMyAnswer() != null && !scoreInfoInVO.getMyAnswer().isEmpty()) {
                    String[] questionAnswerMore = scoreInfoInVO.getMyAnswer().split(",");
                    scoreInfoOutVO.setMyAnswerMore(questionAnswerMore);
                }
            }else {
                if(scoreInfoInVO.getMyAnswer() != null && !scoreInfoInVO.getMyAnswer().isEmpty()){
                    scoreInfoOutVO.setMyAnswer(scoreInfoInVO.getMyAnswer());
                }
            }
            if(scoreInfoInVO.getIsRight() != null){
                scoreInfoOutVO.setIsRight(scoreInfoInVO.getIsRight());
            }
            if(scoreInfoInVO.getGetValue() != null){
                scoreInfoOutVO.setGetValue(scoreInfoInVO.getGetValue());
            }
            scoreInfoOutVOS.add(scoreInfoOutVO);
        }
        return scoreInfoOutVOS;
    }

    public static List<String> validateNotEmpty(String value, String fieldName) {
        List<String> errors = new ArrayList<>();
        if (value == null || value.trim().isEmpty()) {
            errors.add(fieldName + "不能为空");
        }
        return errors;
    }

    public static List<String> validateLength(String value, int minLength, int maxLength, String fieldName) {
        List<String> errors = new ArrayList<>();
        String trimmedValue = value.trim();
        if (trimmedValue.length() < minLength || trimmedValue.length() > maxLength) {
            errors.add(fieldName + "长度必须在" + minLength + "到" + maxLength + "之间");
        }
        return errors;
    }

    public static List<String> validateNoSpecialChar(String value, String fieldName) {
        List<String> errors = new ArrayList<>();
        if (SPECIAL_CHAR_PATTERN.matcher(value).find()) {
            errors.add(fieldName + "不能包含空格和特殊字符");
        }
        return errors;
    }

    public static List<String> validateNumeric(String value, String fieldName) {
        List<String> errors = new ArrayList<>();
        if (!value.matches("\\d+")) {
            errors.add(fieldName + "只能包含数字");
        }
        return errors;
    }

    public static List<String> validate(String value, int minLength, int maxLength, boolean noSpecialChar, String fieldName) {
        List<String> errorMessages = new ArrayList<>();
        errorMessages.addAll(validateNotEmpty(value, fieldName));
        errorMessages.addAll(validateLength(value, minLength, maxLength, fieldName));
        if (noSpecialChar) {
            errorMessages.addAll(validateNoSpecialChar(value, fieldName));
        }
        return errorMessages;
    }

    /**
     * 根据当前登录用户获取他的顶级学校名称
     */
    public static String findTopLevelSchoolName(SysUserRoleMapper sysUserRoleMapper, SysDeptMapper sysDeptMapper,SysUserMapper sysUserMapper,Long userId) {
        if(userId == null) {
            userId = SecurityUtils.getUserId();
        }
        Long[] roleIds = sysUserRoleMapper.selectRoleIdbyUserId(userId);
        String topLevelParentName = "";
        if(roleIds == null || roleIds.length == 0) {
            return topLevelParentName;
        }
        Long roleId = roleIds[0];
        if(roleId != 5 && roleId != 1 && roleId != 6){
            SysUser user = sysUserMapper.selectUserById(userId);
            if(null == user){
                return topLevelParentName;
            }
            Long schoolId = user.getSchoolId();
            topLevelParentName = sysDeptMapper.selectDeptById(schoolId).getDeptName();
        }else if(roleId == 1 || roleId == 6){
            topLevelParentName = "河南伟达电子技术有限公司";
        }
        return topLevelParentName;
    }

    /**
     * 递归查找顶级父类部门
     *
     * @param deptId 当前部门ID
     * @param sysDeptMapper SysDeptMapper实例
     * @return 顶级父类部门
     */
    public static SysDept findTopLevelParent(Long deptId, SysDeptMapper sysDeptMapper) {
        SysDept dept = sysDeptMapper.selectDeptById(deptId);
        if (dept != null && dept.getParentId() != 0) {
            return findTopLevelParent(dept.getParentId(), sysDeptMapper);
        }
        return dept;
    }

    /**
     * 将逗号分隔的字符串转换为指定类型的数组
     *
     * @param str    输入字符串
     * @param mapper 转换函数，例如 Integer::valueOf、Long::valueOf
     * @param clazz  数组元素的类型
     * @param <T>    泛型类型
     * @return 转换后的数组，若输入为空或无效则返回空数组
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] stringToArray(String str, Function<String, T> mapper, Class<T> clazz) {
        if (str == null || str.isEmpty()) {
            // 返回空数组
            return (T[]) Array.newInstance(clazz, 0);
        }
        String[] strArr = str.split(",");
        // 使用 mapper 转换并创建数组
        return Arrays.stream(strArr)
                .map(mapper)
                .toArray(size -> (T[]) Array.newInstance(clazz, size));
    }


    public static Long[] StringToLongArray(String arr){
        if(StringUtils.isEmpty(arr)){
            return null;
        }
        String[] strArr = arr.split(",");
        return Arrays.stream(strArr)
                .map(Long::valueOf)
                .toArray(Long[]::new);
    }



    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        //putIfAbsent方法添加键值对，如果map集合中没有该key对应的值，则直接添加，并返回null，如果已经存在对应的值，则依旧为原来的值。
        //如果返回null表示添加数据成功(不重复)，不重复(null==null :TRUE)
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    public static LocalDateTime getStartDate(Integer time) {
        if (time == null || time == 0) {
            return null; // 不筛选时间
        } else if (time == 1) {
            return LocalDate.now().minusDays(1).atStartOfDay(); // 一日内
        } else if (time == 2) {
            return LocalDate.now().minusWeeks(1).atStartOfDay(); // 一周内
        } else if (time == 3) {
            return LocalDate.now().minusMonths(1).atStartOfDay(); // 一月内
        } else if (time == 4) {
            return LocalDate.now().minusMonths(3).atStartOfDay(); // 三月内
        } else if (time == 5) {
            return LocalDate.now().minusMonths(6).atStartOfDay(); // 半年内
        } else if (time == 6) {
            return LocalDate.now().minusYears(1).atStartOfDay(); // 一年内
        }
        return LocalDateTime.now(); // 默认返回当前时间
    }

    public static Map<Long, Set<String>> getCourseLearningRecords(Long courseId,RedisCache redisCache) {
        Long userId;
        try {
            userId = SecurityUtils.getUserId();
        } catch (ServiceException e) {
            return null;
        }

        // Redis Key
        String redisKey = "user_course:" + userId + ":" + courseId;

        // 获取该课程下所有 sectionId 及其文件 URL
        Map<String, String> sectionFilesMap = redisCache.getCacheMap(redisKey);

        if (sectionFilesMap == null || sectionFilesMap.isEmpty()) {
            return Collections.emptyMap();
        }

        // 解析 JSON 为 Map
        Map<Long, Set<String>> result = new HashMap<>();
        for (Map.Entry<String, String> entry : sectionFilesMap.entrySet()) {
            Long sectionId = Long.parseLong(entry.getKey());
            Set<String> fileSet = new HashSet<>(JSONArray.parseArray(entry.getValue(), String.class));
            result.put(sectionId, fileSet);
        }

        return result;
    }

    // 计算时间差的方法
    public static BigDecimal calculateTotalTimeDifference(List<TimePeriod> timePeriods, String unit) {
        // 时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        BigDecimal totalTimeDifference = BigDecimal.ZERO;

        // 遍历集合中的每个 TimePeriod 计算时间差
        for (TimePeriod timePeriod : timePeriods) {
            // 将字符串转换为 LocalDateTime
            LocalDateTime start = LocalDateTime.parse(timePeriod.getStartTime(), formatter);
            LocalDateTime end = LocalDateTime.parse(timePeriod.getEndTime(), formatter);

            // 计算两个时间之间的差值
            Duration duration = Duration.between(start, end);

            // 获取总秒数
            long totalSeconds = duration.getSeconds();

            // 根据单位返回差值并累加到 totalTimeDifference 中
            if ("h".equalsIgnoreCase(unit)) {
                // 转换为小时并计算小数部分
                BigDecimal hours = new BigDecimal(totalSeconds).divide(new BigDecimal(3600), 10, RoundingMode.HALF_UP);
                totalTimeDifference = totalTimeDifference.add(hours);
            } else if ("m".equalsIgnoreCase(unit)) {
                // 转换为分钟并计算小数部分
                BigDecimal minutes = new BigDecimal(totalSeconds).divide(new BigDecimal(60), 10, RoundingMode.HALF_UP);
                totalTimeDifference = totalTimeDifference.add(minutes);
            } else {
                throw new IllegalArgumentException("Invalid unit. Use 'h' or 'm'.");
            }
        }

        // 保留一位小数
        return totalTimeDifference.setScale(1, RoundingMode.HALF_UP);
    }

}
